package com.acme.domain.account;

import com.acme.exceptions.NoEnoughFundsException;
import com.acme.exceptions.OverDraftLimitExceededException;

public class CheckingAccount extends AbstractAccount {

    private double overdraft;

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (!(o instanceof CheckingAccount)) return false;

        CheckingAccount that = (CheckingAccount) o;

        if ((Double.compare(that.overdraft, overdraft) != 0) || (Double.compare(that.balance, balance) != 0))
            return false;

        return true;
    }

    @Override
    public int hashCode() {
    	//TODO: [VY] Ok. Please don't use ?: next time ;)
        long temp = overdraft != +0.0d ? Double.doubleToLongBits(overdraft) : 0L;
        return (int) (temp ^ (temp >>> 32));
    }

    public CheckingAccount(final int id, final double amount,
                           final double overdraft) {
        super(id, amount);
        this.overdraft = overdraft;
    }

    @Override
    public void withdraw(final double amount) throws NoEnoughFundsException {
        if (amount < 0) {
            throw new IllegalArgumentException("Amount can not be negative");
        }
        if (this.balance - amount >= -overdraft) {
            this.balance -= amount;
        } else {
            throw new NoEnoughFundsException(amount);
        }

        if (this.balance < amount) {
            // Not enough balance to cover the amount requested to withdraw
            // Check if there is enough in the overdraft protection (if any)
            double overdraftNeeded = amount - this.balance;
            if (overdraft < overdraftNeeded) {
                throw new OverDraftLimitExceededException(overdraftNeeded
                        - overdraft);
            } else {
                // Yes, there is overdraft protection and enough to cover the
                // amount
                this.balance = 0.0;
                overdraft -= overdraftNeeded;
            }
        } else {
            // Yes, there is enough balance to cover the amount
            // Proceed as usual
            this.balance = this.balance - amount;
        }


    }

    @Override
    public void deposit(final double amount) {
        if (amount > 0) {
            this.balance += amount;
        } else {
            throw new IllegalArgumentException("amount ca not be negative");
        }

    }


    @Override
    public String toString() {
        final StringBuffer sb = new StringBuffer();
        sb.append("CheckingAccount");
        sb.append("{balance: ").append(balance);
        sb.append(",overdraft: ").append(overdraft);
        sb.append("}");
        return sb.toString();
    }

    public AccountType getAccountType() {
        return AccountType.CHECKING;
    }

    public double getOverdraft() {
        return overdraft;
    }
}
